/* ==================================================================
* Copyright (c) 2024/11/15 SCNU LiuJunJie z-ken
* All rights reserved.
* fileName:	analyseRecord.h
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the xxx Group. and
* its contributors.
* 4. Neither the name of the Group nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Author,GROUP AND CONTRIBUTORS
* ===================================================================
* Author: LiuJunJie z-ken.
*/

//
// Created by zken on 2024/11/4.
//
#include <iostream>
#include <string>
#include <stack>
#include <queue>
#include <algorithm>
#include <set>
#include "util.h"
#include "production.h"
#include "astTreeNode.h"
#include "FourthTuple.h"

using namespace std;

#ifndef PROJECTLIZE_ANALYSERECORD_H
#define PROJECTLIZE_ANALYSERECORD_H

class AST_TREE_ERROR : std::exception {
public:
    string msg = "语法树错误，请检查你的语法，或者检测你选择的属性文法！";

    // 构造函数
    AST_TREE_ERROR(const std::string &message) : msg(message) {}

    AST_TREE_ERROR() {}

    // 重写 what() 方法
    const char *what() const noexcept override {
        return msg.c_str();
    }
};


/**
 * 分析栈中的分析量
 */
class AnalyseValue // 分析量，包含文法中的分析类型，和这个分析类型对应的真实值
{
public:
    string tokenType; // token的类型，对应文法的类型
    string tokenContent; // token的值，对应未编码文件的原型值
    AstTreeNode *ptr;
    AstTreeNode *ptr2;
    FourthTuple fTuple;

    static string stackToString(stack<AnalyseValue> s, int reverse1 = false);

    static string queueToString(queue<AnalyseValue> q);


    AnalyseValue() {}

    AnalyseValue(string tokenType, string tokenContent) {
        this->ptr = nullptr;
        this->ptr2 = nullptr;
        this->tokenType = tokenType;
        this->tokenContent = tokenContent;
    }

};

/**
 * 分析表的一行
 */
class analyseRecord {
public:
    int lineId;// 行号
    string statusStackStatus;//状态栈的状态
    string characterStackStatus;//符号栈栈的状态
    string inputQueueStatus;//输入队列的状态
    string action; // 进行的动作
    string gotoContent;//如果进行了reduce，那么要进行goto
    analyseRecord();

    analyseRecord(stack<int> status, stack<AnalyseValue> characterStatus, queue<AnalyseValue> inputQueueStatus);

    string getDetails();
};

/**
 * AST抽象分析树
 */
class AstTree {
private:
    // 文法器件
    ProductionUtil *productionUtil1;

public:

    void setProductionUtil(ProductionUtil *util);

    // 依照文法规则进行属性文法构造抽象语法树 -- makeNode是无法统一抽象的，必须一一进行
//    AstTreeNode *makeNode(int productionId, vector<AnalyseValue> values);

    AstTreeNode *makeLeaf(AnalyseValue value);

    AstTreeNode *root = nullptr;

    string productionsName;//文法的名称-根据文法的名称不同进行不同的操作

    /**
     * 属性文法的执行函数，根据传入的productionsName指定属性文法的策略
     * @param productionId
     * @param values
     * @return
     */
    AstTreeNode *doAttribute(int productionId, vector<AnalyseValue> values);

    /**
     * minic的属性文法执行
     * @param productionId
     * @param values
     * @return
     */
    AstTreeNode *doAttribute_minic(int productionId, vector<AnalyseValue> values);

    /**
     * tiny的属性文法执行
     * @param productionId
     * @param values
     * @return
     */
    AstTreeNode *doAttribute_tiny(int productionId, vector<AnalyseValue> values);

    /**
     * exp表达式的属性文法执行
     * @param productionId
     * @param values
     * @return
     */
    AstTreeNode *doAttribute_exp(int productionId, vector<AnalyseValue> values);


    /**
     *  深度搜索,展示抽象语法树
     */
    void showAstTree();

private:
    /**
     * showTreeNodes的辅助函数
     * @param root
     * @param depth
     */
    void showTreeNodesSupport(AstTreeNode *root, int depth);
};

#endif //PROJECTLIZE_ANALYSERECORD_H
